#include "qtcv_static.h"

QTCV_static::QTCV_static(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	init();
	cropper = NULL;
}

QTCV_static::~QTCV_static()
{
	
}

void QTCV_static::init(void)
{
	maxFrames = -1;
		 
	this->resize(840, 680);
	setWindowTitle("Video Cropper - Joed Lopes - UFPR - Brazil");

	QWidget *qwidtop = new QWidget();

	ui.mainToolBar->addWidget(qwidtop);

	topLayout = new QVBoxLayout(qwidtop);
	boxButtons = new QHBoxLayout();
	boxButtons->setAlignment(Qt::AlignLeft);	
	boxProps = new QHBoxLayout();
	boxProps->setAlignment(Qt::AlignLeft);

	topLayout->addLayout(boxButtons);
	topLayout->addLayout(boxProps);


	btnProcess = new QPushButton("Process");
	btnOpenFile = new QPushButton("Open File");
	btnPreview = new QPushButton("Preview");
	btnShowInfo = new QPushButton("Show Info");
	btnSave = new QPushButton("Set Output File");

	boxButtons->setSpacing(5); boxProps->setSpacing(5);

	boxButtons->addWidget(btnOpenFile);
	boxButtons->addWidget(btnSave);
	boxButtons->addWidget(btnProcess);
	boxButtons->addWidget(btnPreview);
	boxButtons->addWidget(btnShowInfo);
	
	doubleValidator = new QDoubleValidator(-100, 100, 2,this);
	editResize = new QLineEdit("100.00");
	editResize->setValidator(doubleValidator); editResize->setFixedWidth(100);
	lbResize = new QLabel("Resize to (%):"); 
	
	boxProps->addWidget(lbResize);
	boxProps->addWidget(editResize);

	lbRect = new QLabel("ROI (x,y,w,h):");
	
	editRect = new QLineEdit("0,0,0,0");	
	editRect->setFixedWidth(200);	

	boxProps->addWidget(lbRect);
	boxProps->addWidget(editRect);
	
	lbEnd = new QLabel("End:");   lbEnd->setFixedWidth(50);
	lbInit = new QLabel("Init:"); lbInit->setFixedWidth(50);
	editEnd = new QLineEdit(""); 
	editEnd->setFixedWidth(100);
	editInit = new QLineEdit("");
	editInit->setFixedWidth(100);

	editEnd->setValidator(new QDoubleValidator(0,1000000,0,this));
	editInit->setValidator(new QDoubleValidator(0, 1000000, 0, this));

	boxProps->addWidget(lbInit);
	boxProps->addWidget(editInit);
	boxProps->addWidget(lbEnd);
	boxProps->addWidget(editEnd);


	connect(btnProcess, SIGNAL(clicked()), this, SLOT(btnProcess_clicked()));
	connect(btnOpenFile, SIGNAL(clicked()), this, SLOT(btnOpenFile_clicked()));
	connect(btnPreview, SIGNAL(clicked()), this, SLOT(btnPreview_clicked()));
	connect(btnShowInfo, SIGNAL(clicked()), this, SLOT(btnShowInfo_clicked()));
	connect(btnSave, SIGNAL(clicked()), this, SLOT(btnSave_clicked()));


	qScrollArea = new QScrollArea();
	qScrollArea->setBackgroundRole(QPalette::Dark);

	imgWid = new ImageWidget();
	qScrollArea->setWidget(imgWid);


	box = new QVBoxLayout();
	ui.centralWidget->setLayout(box);

	splitter = new QSplitter(Qt::Vertical);
	splitter->setHandleWidth(3);
	splitter->setLineWidth(3);
	//splitter->setStyleSheet(tr("QSplitter::handle:horizontal {background: qlineargradient(x1 : 0, y1 : 0, x2 : 1, y2 : 1, stop : 0 #eee, stop:1 #ccc);border: 1px solid #777;width: 13px;margin - top: 2px;margin - bottom: 2px;border - radius: 4px;}"));

	mainBox = new QWidget();
	boxImages = new QHBoxLayout();
	mainBox->setLayout(boxImages);
	
	boxImages->addWidget(qScrollArea);

	//list info

	listInfo = new QListView();
	modelListInfo = new QStandardItemModel();
	listInfo->setModel(modelListInfo);

	//slider
	wSlider = new QWidget();
	boxSlider = new QVBoxLayout(wSlider);
	labelSlider = new QLabel("Frame: no file selected");

	sliderFrames = new QSlider(Qt::Horizontal);
	sliderFrames->setMaximumHeight(20);
	sliderFrames->setMinimum(0);
	sliderFrames->setMaximum(0);
	sliderFrames->setEnabled(false);

	connect(sliderFrames, SIGNAL(sliderReleased()), this, SLOT(slider_valueChanged()));
	connect(sliderFrames, SIGNAL(sliderMoved(int)), this, SLOT(slider_sliderMoved(int)));
	connect(sliderFrames, SIGNAL(valueChanged(int)), this, SLOT(slider_sliderMoved(int)));

	splitter->addWidget(mainBox);
	splitter->addWidget(wSlider);
	splitter->addWidget(listInfo);

	boxSlider->setAlignment(Qt::AlignBottom | Qt::AlignLeft);
	boxSlider->addWidget(labelSlider, 0);
	boxSlider->addWidget(sliderFrames);

	QList<int> sizes; sizes << 600 << 30 << 200; splitter->setSizes(sizes);

	box->addWidget(splitter);

	textStatus = new QLabel("");
	textStatus->setMinimumWidth(150);
	textStatus->setMinimumWidth(150);
	ui.statusBar->addWidget(textStatus, 0);

	progressBar = new QProgressBar();
	progressBar->setMinimumWidth(600);
	progressBar->setMinimum(0); progressBar->setValue(0);
	ui.statusBar->addWidget(progressBar, 1);
	ui.statusBar->layout()->setMargin(10);
	progressBar->setVisible(false);


	connect(imgWid, SIGNAL(sendRect(QString)), this, SLOT(sendRect(QString)));

}

void QTCV_static::btnShowInfo_clicked(void)
{
	listInfo->setVisible(!listInfo->isVisible());
}

void QTCV_static::btnOpenFile_clicked(void)
{
	pathInputVideo = fileDialog.getOpenFileName(this, tr("Open Input Video File"), "", tr("Video (*.avi *.mpg *.mpeg *.mp4 *.wmv)"));

	if (pathInputVideo.size() > 0)
	{
		addMessageToInfoBox(tr("Input Video File selected: ").append(pathInputVideo));

		if (cap.open(pathInputVideo.toStdString()))
		{
			QThread::msleep(500);
			Mat frame;
			if (cap.read(frame))
			{
				QPixmap pix;
				if (frame.channels() > 1)
				{
					QImage qImage((uchar*)frame.data, frame.cols, frame.rows, frame.step1(), QImage::Format_RGB888);
					pix = QPixmap::fromImage(qImage.rgbSwapped());
				}
				else
				{
					QImage qImage((uchar*)frame.data, frame.cols, frame.rows, frame.step1(), QImage::Format_Indexed8);
					pix = QPixmap::fromImage(qImage);
				}
				imgWid->setImage(pix);

				int w = (int)cap.get(CV_CAP_PROP_FRAME_WIDTH);
				int h = (int)cap.get(CV_CAP_PROP_FRAME_HEIGHT);

				double fps = (double)cap.get(CV_CAP_PROP_FPS);
				unsigned long frameCount = (unsigned long)cap.get(CV_CAP_PROP_FRAME_COUNT);

				maxFrames = frameCount;

				char str[100]; memset(str, 0, 100);
				sprintf(str, "Dimensions: %d x %d | FPS: %f | Total Frames: %lu", w,h,fps,frameCount);

				addMessageToInfoBox(tr("File Opened: ").append(pathInputVideo));
				addMessageToInfoBox(QString(str));

				sliderFrames->setEnabled(true);
				sliderFrames->setMinimum(0);
				sliderFrames->setMaximum(frameCount);

				

				return;
			}
		}
		cap.release();
	}
	else
	{
		addMessageToInfoBox(tr("Input Video File not selected."));
	}
}

void QTCV_static::btnPreview_clicked(void)
{
	if (cropper == NULL)
	{

		if (pathInputVideo.size() > 0)
		{

			QList<QString> list = editRect->text().split(",");

			int w, h, x, y;
			x = h = y = w = 0;
			if (list.size() == 4)
			{
				x = list[0].toInt();
				y = list[1].toInt();
				w = list[2].toInt();
				h = list[3].toInt();
			}
			else
			{
				addMessageToInfoBox("Error: Region of Interest (ROI) not selected.");
			}

			QString text = editResize->text();
			float scale = text.toFloat() / 100.0;

			text = editInit->text();
			long cap_init = text.toUInt();
			text = editEnd->text();
			long cap_end = text.toUInt();

			if (cap_end == 0)
			{
				cap_end = maxFrames;
			}

			mutexCropper = new QMutex();
			cropper = new VideoCropper(mutexCropper, this);
			cropper->setInputFile(pathInputVideo.toStdString());
			cropper->setROI(cv::Rect(x, y, w, h));
			cropper->setRescaleFactor(scale);
			cropper->setInitEnd(cap_init, cap_end);

			connect(cropper, SIGNAL(process_finished()), this, SLOT(process_finished()));
			connect(cropper, SIGNAL(send_position(long, long)), this, SLOT(sendProgressBar(long, long)));
			cropper->startPreview();
		}
		else
		{
			addMessageToInfoBox("Error: input file not selected");
		}
	}
	else
	{
		cropper->stopProcess();
		cropper->wait();
		delete cropper;
		cropper = NULL;
	}
}

void QTCV_static::btnProcess_clicked(void)
{
	if (cropper == NULL)
	{

		if (pathInputVideo.size() > 0 && pathOutputVideoFile.size() > 0)
		{
			QList<QString> list = editRect->text().split(",");

			int w, h, x, y;
			x = h = y = w = 0;
			if (list.size() == 4)
			{
				x = list[0].toInt();
				y = list[1].toInt();
				w = list[2].toInt();
				h = list[3].toInt();
			}
			else
			{
				addMessageToInfoBox("Error: Region of Interest (ROI) not selected.");
			}

			QString text = editResize->text();
			float scale = text.toFloat() / 100.0;

			text = editInit->text();
			long cap_init = text.toUInt();
			text = editEnd->text();
			long cap_end = text.toUInt();

			if (cap_end == 0)
			{
				cap_end = maxFrames;
			}

			mutexCropper = new QMutex();
			cropper = new VideoCropper(mutexCropper, this);
			connect(cropper, SIGNAL(process_finished()), this, SLOT(process_finished()));
			connect(cropper, SIGNAL(send_position(long, long)), this, SLOT(sendProgressBar(long, long)));
			cropper->setInputFile(pathInputVideo.toStdString());
			cropper->setOutputFile(pathOutputVideoFile.toStdString());
			cropper->setROI(cv::Rect(x, y, w, h));
			cropper->setInitEnd(cap_init, cap_end);
			cropper->setRescaleFactor(scale);
			cropper->startProcess();
		}
		else
		{
			addMessageToInfoBox("Error: input or output file not selected");
		}
	}
	else
	{
		cropper->stopProcess();
		cropper->wait();
		delete cropper;
		cropper = NULL;
	}
}

void QTCV_static::btnSave_clicked(void)
{
	pathOutputVideoFile = fileDialog.getSaveFileName(this, "Save Video Output File", pathOutputVideoFile, tr("Video File (*.avi)"));
	
	if (pathOutputVideoFile.size() > 0)
	{
		addMessageToInfoBox(tr("Output Video File selected: ").append(pathOutputVideoFile));
	}
	else
	{
		addMessageToInfoBox(tr("Output File not selected."));
	}
}

void QTCV_static::process_finished(void)
{
	cropper->stopProcess();
	cropper->wait();
	delete cropper;
	cropper = NULL;	
}

void QTCV_static::addMessageToInfoBox(QString msg)
{
	msg = QDateTime::currentDateTime().time().toString().append(": ").append(msg);
	QStandardItem *item = new QStandardItem(msg);
	modelListInfo->insertRow(0, item);
}

void QTCV_static::setStatusBarText(QString text)
{
	textStatus->setText(text);
}

void QTCV_static::sendProgressBar(long max, long value)
{
	progressBar->setVisible(max >= 0);
	progressBar->setMaximum(max);
	progressBar->setValue(value);
}

void QTCV_static::sendRect(QString data)
{
	editRect->setText(data);
}


void QTCV_static::slider_valueChanged()
{
	if (cap.isOpened())
	{
		int value = sliderFrames->value();

		labelSlider->setText(tr("Frame: ").append(QString::number(value)).append("/").append(QString::number(maxFrames)));

		cap.set(CV_CAP_PROP_POS_FRAMES, value);
		Mat frame;
		if (cap.read(frame))
		{
			QPixmap pix;
			if (frame.channels() > 1)
			{
				QImage qImage((uchar*)frame.data, frame.cols, frame.rows, frame.step1(), QImage::Format_RGB888);
				pix = QPixmap::fromImage(qImage.rgbSwapped());
			}
			else
			{
				QImage qImage((uchar*)frame.data, frame.cols, frame.rows, frame.step1(), QImage::Format_Indexed8);
				pix = QPixmap::fromImage(qImage);
			}
			imgWid->setImage(pix);
		}
	}
}

void QTCV_static::slider_sliderMoved(int)
{
	slider_valueChanged();
}
